package com.getpebble.android.framework.endpoint;

import android.content.Context;
import android.os.Handler;
import android.os.Looper;
import com.getpebble.android.R;
import com.getpebble.android.bluetooth.protocol.ProtocolMessage;
import com.getpebble.android.common.core.trace.Trace;
import com.getpebble.android.common.model.FrameworkState;
import com.getpebble.android.framework.protocol.EndpointId;
import com.getpebble.android.framework.protocol.inbound.PblInboundCoreDumpMessage;
import com.getpebble.android.framework.protocol.inbound.PblInboundCoreDumpMessage.CoreDumpError;
import com.getpebble.android.framework.protocol.inbound.PblInboundCoreDumpMessage.CoreDumpResponse;
import com.getpebble.android.framework.protocol.outbound.PblOutboundCoreDumpMessage;
import com.google.common.collect.ImmutableSet;
import com.google.common.primitives.UnsignedInteger;
import com.sun.mail.imap.protocol.ListInfo;
import com.sun.mail.smtp.SMTPMessage;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.util.Set;
import java.util.concurrent.atomic.AtomicInteger;

public class CoreDumpEndpoint extends RequestableEndpoint {
    public static final String TAG = CoreDumpEndpoint.class.getSimpleName();
    private static AtomicInteger mTransactionSequenceInt = new AtomicInteger(0);
    private UnsignedInteger mBytesSoFar = UnsignedInteger.fromIntBits(0);
    private Context mContext;
    private File mFile;
    private FrameworkState mFrameworkState;
    private Handler mHandler;
    private int mLogCount;
    private IEndpointMessageSender mMessageSender;
    private UnsignedInteger mNumBytes;
    private Runnable mTimeoutRunnable = new Runnable() {
        public void run() {
            CoreDumpEndpoint.this.sendResult(CoreDumpResult.ERROR_TIMEOUT);
        }
    };

    static /* synthetic */ class AnonymousClass2 {
        static final /* synthetic */ int[] $SwitchMap$com$getpebble$android$framework$protocol$inbound$PblInboundCoreDumpMessage$CoreDumpError = new int[CoreDumpError.values().length];

        static {
            try {
                $SwitchMap$com$getpebble$android$framework$protocol$inbound$PblInboundCoreDumpMessage$CoreDumpError[CoreDumpError.NO_ERROR.ordinal()] = 1;
            } catch (NoSuchFieldError e) {
            }
            try {
                $SwitchMap$com$getpebble$android$framework$protocol$inbound$PblInboundCoreDumpMessage$CoreDumpError[CoreDumpError.MALFORMED_REQUEST.ordinal()] = 2;
            } catch (NoSuchFieldError e2) {
            }
            try {
                $SwitchMap$com$getpebble$android$framework$protocol$inbound$PblInboundCoreDumpMessage$CoreDumpError[CoreDumpError.ALREADY_IN_PROGRESS.ordinal()] = 3;
            } catch (NoSuchFieldError e3) {
            }
            try {
                $SwitchMap$com$getpebble$android$framework$protocol$inbound$PblInboundCoreDumpMessage$CoreDumpError[CoreDumpError.IMAGE_DOES_NOT_EXIST.ordinal()] = 4;
            } catch (NoSuchFieldError e4) {
            }
            try {
                $SwitchMap$com$getpebble$android$framework$protocol$inbound$PblInboundCoreDumpMessage$CoreDumpError[CoreDumpError.IMAGE_CORRUPT.ordinal()] = 5;
            } catch (NoSuchFieldError e5) {
            }
        }
    }

    public enum CoreDumpResult {
        SUCCESS(0),
        NO_CORE_DUMP(1),
        ERROR_INVALID_TRANSACTION_ID(-1),
        ERROR_INVALID_BYTE_OFFSET(-2),
        ERROR_FILE_WRITE_FAILED(-3),
        ERROR_MALFORMED_REQUEST(-4),
        ERROR_ALREADY_IN_PROGRESS(-5),
        ERROR_CORRUPT(-6),
        ERROR_PRF(-7),
        ERROR_TIMEOUT(-8),
        ERROR_UNKNOWN(-9),
        ERROR_INVALID(-10),
        ERROR_DISCONNECTED(-11);
        
        private int mValue;

        private CoreDumpResult(int value) {
            this.mValue = value;
        }

        public int getValue() {
            return this.mValue;
        }

        public static CoreDumpResult fromValue(int value) {
            for (CoreDumpResult result : values()) {
                if (result.getValue() == value) {
                    return result;
                }
            }
            return ERROR_UNKNOWN;
        }
    }

    public CoreDumpEndpoint(Context context, IEndpointMessageSender messageSender) throws IllegalArgumentException {
        if (context == null) {
            throw new IllegalArgumentException("'context' cannot be null!");
        } else if (messageSender == null) {
            throw new IllegalArgumentException("'messageSender' cannot be null!");
        } else {
            this.mContext = context;
            this.mMessageSender = messageSender;
            this.mHandler = new Handler(Looper.getMainLooper());
        }
    }

    private Context getContext() {
        return this.mContext;
    }

    private IEndpointMessageSender getMessageSender() {
        return this.mMessageSender;
    }

    private void sendResult(CoreDumpResult result) {
        Trace.debug(TAG, "Sending result: " + result);
        String filename = null;
        if (this.mFile != null) {
            filename = this.mFile.getAbsolutePath();
        }
        if (this.mFrameworkState != null) {
            this.mFrameworkState.setCoreDumpResult(result.getValue(), filename);
        }
        cleanup();
    }

    private void cleanup() {
        this.mFrameworkState = null;
        this.mNumBytes = null;
        this.mBytesSoFar = UnsignedInteger.fromIntBits(0);
    }

    public byte getNextTransactionId() {
        mTransactionSequenceInt.incrementAndGet();
        return mTransactionSequenceInt.byteValue();
    }

    public byte getTransactionId() {
        return mTransactionSequenceInt.byteValue();
    }

    boolean onRequest(EndpointRequest request, FrameworkState frameworkState) {
        this.mFrameworkState = frameworkState;
        sendCoreDumpRequest();
        return true;
    }

    private void startTimeout() {
        this.mHandler.postDelayed(this.mTimeoutRunnable, 5000);
    }

    private void cancelTimeout() {
        this.mHandler.removeCallbacks(this.mTimeoutRunnable);
    }

    private void sendCoreDumpRequest() {
        File oldCoreDump = getFile();
        if (oldCoreDump.exists()) {
            if (oldCoreDump.delete()) {
                Trace.debug(TAG, "Removed old core-dump file");
            } else {
                Trace.error(TAG, "Failed to remove old core dump file");
            }
        }
        this.mFile = null;
        this.mLogCount = 0;
        Trace.verbose(TAG, "Starting core dump");
        PblOutboundCoreDumpMessage message = new PblOutboundCoreDumpMessage(getNextTransactionId());
        startTimeout();
        getMessageSender().sendMessage(message);
    }

    boolean onPrfRequest(EndpointRequest request, FrameworkState frameworkState) {
        this.mFrameworkState = frameworkState;
        sendResult(CoreDumpResult.ERROR_PRF);
        return true;
    }

    Set<EndpointId> getSupportedEndpoints() {
        return ImmutableSet.of(EndpointId.CORE_DUMP);
    }

    boolean onReceive(ProtocolMessage message) {
        cancelTimeout();
        PblInboundCoreDumpMessage coreDumpMessage = new PblInboundCoreDumpMessage(message);
        if (coreDumpMessage.getTransactionId() != getTransactionId()) {
            sendResult(CoreDumpResult.ERROR_INVALID_TRANSACTION_ID);
        } else {
            sendPingIfRequired();
            if (coreDumpMessage.getResponse().equals(CoreDumpResponse.IMAGE_INFO)) {
                handleImageInfo(coreDumpMessage);
            } else {
                handleImageData(coreDumpMessage);
            }
        }
        return true;
    }

    private void handleImageInfo(PblInboundCoreDumpMessage coreDumpMessage) {
        CoreDumpResult result = mapErrorToResult(coreDumpMessage.getError());
        if (result != null) {
            sendResult(result);
            return;
        }
        this.mNumBytes = coreDumpMessage.getNumBytes();
        startTimeout();
    }

    private CoreDumpResult mapErrorToResult(CoreDumpError error) {
        switch (AnonymousClass2.$SwitchMap$com$getpebble$android$framework$protocol$inbound$PblInboundCoreDumpMessage$CoreDumpError[error.ordinal()]) {
            case SMTPMessage.RETURN_HDRS /*2*/:
                return CoreDumpResult.ERROR_MALFORMED_REQUEST;
            case ListInfo.INDETERMINATE /*3*/:
                return CoreDumpResult.ERROR_ALREADY_IN_PROGRESS;
            case SMTPMessage.NOTIFY_DELAY /*4*/:
                return CoreDumpResult.NO_CORE_DUMP;
            case R.styleable.WalletFragmentStyle_maskedWalletDetailsHeaderTextAppearance /*5*/:
                return CoreDumpResult.ERROR_CORRUPT;
            default:
                return null;
        }
    }

    private void sendPingIfRequired() {
        if (this.mFrameworkState != null) {
            int i = this.mLogCount;
            this.mLogCount = i + 1;
            if (i % 50 == 0) {
                this.mFrameworkState.sendLogCoreDumpPing();
            }
        }
    }

    private void handleImageData(PblInboundCoreDumpMessage coreDumpMessage) {
        Trace.debug(TAG, "Got Image data");
        if (coreDumpMessage.getByteOffset().equals(this.mBytesSoFar)) {
            writeDataToFile(coreDumpMessage.getImageData());
            coreDumpMessage.getImageData().position(0);
            this.mBytesSoFar = this.mBytesSoFar.plus(UnsignedInteger.fromIntBits(coreDumpMessage.getImageData().remaining()));
            if (this.mBytesSoFar.equals(this.mNumBytes)) {
                Trace.debug(TAG, "Core dump is complete");
                sendResult(CoreDumpResult.SUCCESS);
                return;
            }
            Trace.debug(TAG, "Still waiting for " + this.mNumBytes.minus(this.mBytesSoFar) + " bytes.");
            startTimeout();
            return;
        }
        sendResult(CoreDumpResult.ERROR_INVALID_BYTE_OFFSET);
    }

    private void writeDataToFile(ByteBuffer data) {
        Exception e;
        FileOutputStream fileOutputStream = null;
        try {
            FileOutputStream fileOutputStream2 = new FileOutputStream(getFile(), true);
            try {
                fileOutputStream2.write(data.array(), 0, data.remaining());
                fileOutputStream = fileOutputStream2;
            } catch (Exception e2) {
                e = e2;
                fileOutputStream = fileOutputStream2;
                Trace.error(TAG, "Unhandled exception writing core dump to file", e);
                if (fileOutputStream == null) {
                    try {
                        fileOutputStream.flush();
                        fileOutputStream.close();
                    } catch (IOException e3) {
                        Trace.warning(TAG, "Exception thrown when closing file", e3);
                        return;
                    }
                }
            }
        } catch (Exception e4) {
            e = e4;
            Trace.error(TAG, "Unhandled exception writing core dump to file", e);
            if (fileOutputStream == null) {
                fileOutputStream.flush();
                fileOutputStream.close();
            }
        }
        if (fileOutputStream == null) {
            fileOutputStream.flush();
            fileOutputStream.close();
        }
    }

    private File getFile() {
        if (this.mFile == null) {
            this.mFile = new File(getContext().getExternalCacheDir(), "core-dump-unencrypted.bin");
        }
        return this.mFile;
    }
}
